<template>
  <div class="basic-table">
    <div ref="tableHead" class="basic-table-head">
      <slot name="tableHead" :total="paginationInfo.total"></slot>
    </div>
    <el-table
      border
      v-loading="tableLoading"
      :data="data || tableData"
      :height="tableHeight"
      v-bind="tableProp"
      v-on="tableEvent"
    >
      <el-table-column
        v-for="item in columns"
        :key="item.dataIndex"
        :prop="item.dataIndex"
        :label="item.label"
        :width="item.width"
        :type="item.type ? item.type : null"
        :fixed="item.fixed"
        v-bind="item.tableColumnProp"
      >
        <template #header="{ column }">
          <div class="table-label">{{ column.label }}</div>
        </template>
        <template #default="{ row }" v-if="item.customSlot">
          <slot :name="item.customSlot" :row="row" :schema="item"></slot>
        </template>
      </el-table-column>
      <el-table-column
        v-for="(item, index) in actions"
        :key="index"
        :label="item.label"
        :width="item.width"
        fixed="right"
      >
        <template #header="{ column }">
          <div class="table-label">{{ column.label }}</div>
        </template>
        <template #default="{ row }">
          <div v-if="item.customSlot">
            <slot :name="item.customSlot" :row="row" :action="item"></slot>
          </div>
          <div v-else>
            <el-button
              type="text"
              v-for="(buttonItem, indexB) in item.buttons"
              :key="indexB"
              :style="{ color: buttonItem.color ? buttonItem.color : '' }"
              @click="buttonItem.onClick && buttonItem.onClick(row, buttonItem)"
              >{{ buttonItem.label }}</el-button
            >
          </div>
        </template>
      </el-table-column>
    </el-table>

    <div ref="tableFooterSlot">
      <slot name="tableFooter">
        <div style="height: 32px; margin-top: 16px" v-if="showPagination">
          <el-pagination
            style="float: right"
            background
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="paginationInfo.currentPage"
            :page-sizes="paginationInfo.pageSizes"
            :page-size="paginationInfo.pageSize"
            layout="total, sizes, prev, pager, next, jumper"
            :total="paginationInfo.total"
          ></el-pagination>
        </div>
      </slot>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    tableProp: {
      type: Object,
      default: () => ({}),
    },
    tableEvent: {
      type: Object,
      default: () => ({}),
    },
    tableSchema: {
      type: Array,
      default: () => [],
    },
    api: {
      type: [Function, Promise],
    },
    params: {
      type: Object,
      default: () => ({}),
    },
    beforeFetch: {
      type: Function,
    },
    afterFetch: {
      type: Function,
    },
    rowInfo: {
      type: Object,
      default: () => ({
        rowKey: 'rows',
      }),
    },
    immediateFetch: {
      type: Boolean,
      default: true,
    },
    data: {
      type: Array,
    },
    actions: {
      type: Array,
      default: () => [],
    },
    showPagination: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      columns: [],
      paginationInfo: {
        currentPage: 1,
        pageSizes: [10, 20, 40, 60],
        pageSize: 10,
        total: 0,
      },
      tableHeight: 300,
      tableData: [],
      tableLoading: false,
      resizeObserver: null,
    };
  },
  watch: {
    tableSchema: {
      deep: true,
      immediate: true,
      handler() {
        this.initSchema();
      },
    },
  },
  created() {
    if (this.immediateFetch) {
      this.fetch();
    }
  },
  destroyed() {
    this.resizeObserver.disconnect();
  },
  mounted() {
    this.$nextTick(() => {
      const basicSearchForm = document.querySelectorAll('.basic-search-form');
      const basicOtherBlock = document.querySelectorAll('.basic-other-block');
      // 只有当基础搜索框存在且只存在一个的时候才做表格的自适应高度计算
      if (basicSearchForm.length === 1 || basicOtherBlock.length) {
        this.resizeObserver = new ResizeObserver(() => {
          this.tableHeight =
            document.body.getBoundingClientRect().height -
            (this.$slots.tableHead
              ? this.$refs.tableHead.getBoundingClientRect().bottom + 64
              : this.$refs.tableHead.getBoundingClientRect().bottom + 16) -
            68 +
            (!this.showPagination
              ? 52 - this.$refs.tableFooterSlot.getBoundingClientRect().height
              : 0);
          //console.log(this.tableHeight, '..........');
        });
        this.resizeObserver.observe(
          basicSearchForm[0] || basicOtherBlock[basicOtherBlock.length - 1],
        );
      }
    });
  },
  methods: {
    initSchema() {
      this.columns = this.tableSchema;
    },
    handleSizeChange(val) {
      if (this.paginationInfo.currentPage * val > this.paginationInfo.total) {
        this.paginationInfo.currentPage = 1;
      }
      this.$emit('pagination', { pageNum: this.paginationInfo.currentPage, pageSize: val });
      this.paginationInfo.pageSize = val;
      if (this.api) {
        this.fetch();
      }
      if (this.autoScroll) {
        scrollTo(0, 800);
      }
    },
    handleCurrentChange(val) {
      this.$emit('pagination', { pageNum: val, pageSize: this.paginationInfo.pageSize });
      this.paginationInfo.currentPage = val;
      if (this.api) {
        this.fetch();
      }
      if (this.autoScroll) {
        scrollTo(0, 800);
      }
    },
    fetch() {
      const params = (this.beforeFetch && this.beforeFetch(this.params)) || {};
      this.tableLoading = true;
      this.api &&
        this.api({
          pageNum: this.paginationInfo.currentPage,
          pageSize: this.paginationInfo.pageSize,
          ...params,
        })
          .then((res) => {
            this.paginationInfo.total = res.total || res[this.rowInfo.rowKey].length;
            this.tableData =
              (this.afterFetch && this.afterFetch(res[this.rowInfo.rowKey])) ||
              res[this.rowInfo.rowKey];
          })
          .finally(() => {
            this.tableLoading = false;
          });
    },
  },
};
</script>

<style lang="scss" scoped>
.basic-table {
  background-color: #fff;
  padding: 16px;
  .basic-table-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 16px;
  }
  ::v-deep td.el-table_1_column_1.el-table-column--selection.el-table__cell {
    .cell {
      .el-checkbox {
        display: table;
        margin: 0 auto;
      }
    }
  }
  ::v-deep th.el-table_1_column_1.el-table-column--selection.is-leaf.el-table__cell {
    .cell {
      .el-checkbox {
        display: table;
        margin: 0 auto;
      }
    }
  }
  ::v-deep th.el-table__cell {
    background-color: #f1f1f1;
    .table-label {
      line-height: 20px;
      width: max-content;
      display: flex;
      align-items: center;
      &::before {
        display: block;
        content: '';
        height: 16px;
        padding-right: 8px;
        margin-left: -10px;
        border-left: 1px solid rgba(81, 90, 110, 0.5);
      }
    }
  }
}
</style>
